import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.swing.JPanel;

/**
 * @author shilpa
 * 
 */
public class TPanel extends JPanel {

	final static int WIDTH = (int) Toolkit.getDefaultToolkit().getScreenSize()
			.getWidth();
	final static int HEIGHT = (int) Toolkit.getDefaultToolkit().getScreenSize()
			.getHeight();
	String imageFile;
	String textMessage;
	int xImage;
	int yImage = -1;
	Color defaultColor = Color.black;
	String textColor;
	boolean centerTextOnly = false;
	volatile boolean isPaintStarted = false;
	static TTSReader readText = new TTSReader();
	private static final int EXTERNAL_BUFFER_SIZE = 128000;

	public static final Map<String, Color> nameColorMap = new HashMap<String, Color>();
	static {
		nameColorMap.put("pink", Color.pink);
		nameColorMap.put("black", Color.black);
		nameColorMap.put("blue", Color.blue);
		nameColorMap.put("cyan", Color.cyan);
		nameColorMap.put("dark_gray", Color.DARK_GRAY);
		nameColorMap.put("gray", Color.gray);
		nameColorMap.put("green", Color.green);
		nameColorMap.put("light_gray", Color.LIGHT_GRAY);
		nameColorMap.put("magenta", Color.magenta);
		nameColorMap.put("orange", Color.orange);
		nameColorMap.put("red", Color.red);
		nameColorMap.put("white", Color.white);
		nameColorMap.put("yellow", Color.yellow);
	}

	public TPanel() {
		setPreferredSize(new Dimension(WIDTH, HEIGHT));
		setBackground(Color.WHITE);
	}

	public synchronized void clearPanel() {
		imageFile = null;
		textMessage = null;
		textColor = null;
		centerTextOnly = false;
		repaint();
	}

	public void paint(Graphics g) {
		super.paint(g);
		Graphics2D g2d = (Graphics2D) g;
		if (g2d == null) {
			System.err.println("g2d is null");
		}
		paintImage(g2d);
		paintText(g2d);
		isPaintStarted = false;
	}

	public boolean isValidImage(String name) {
		if (name == null)
			return false;
		name = name.trim().toLowerCase();
		return name.endsWith(".jpg") || name.endsWith(".png")
				|| name.endsWith("jpeg") || name.endsWith("gif");
	}

	private void paintImage(Graphics2D g2d) {
		// System.out.println("paint image...");
		if (!isValidImage(imageFile)) {
			// System.out.println("imageFiel is null so not paintings");
			return;
		}

		BufferedImage image = null;
		try {
			image = ImageIO.read(new File(imageFile));

		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("image exception " + e);
		}

		if (image == null)
			return;

		Insets insets = getInsets();
		int screenWidth = Toolkit.getDefaultToolkit().getScreenSize().width;
		int screenHeight = Toolkit.getDefaultToolkit().getScreenSize().height;

		int width2 = screenWidth / 2;
		int height2 = screenHeight / 2;
		// System.out.println(" image width=" + width2 + " image ht=" +
		// height2);
		int w = width2 - insets.left - insets.right;
		int h = height2 - insets.top - insets.bottom;

		int src_w = image.getWidth(null);
		int src_h = image.getHeight(null);

		double scale_x = ((double) w) / src_w;
		double scale_y = ((double) h) / src_h;

		double scale = Math.min(scale_x, scale_y);

		int dst_w = (int) (scale * src_w);
		int dst_h = (int) (scale * src_h);

		int dx = (screenWidth - dst_w) / 2;
		int dy = (screenHeight - dst_h) / 2;

		// System.out.println(" xloc=" + dx + " yloc =" + dy + " dst_w=" + dst_w
		// + " dst_h=" + dst_h + " src_w=" + src_w + " src_h=" + src_h);
		xImage = dx;
		yImage = dy;
		g2d.drawImage(image, dx, dy, dx + dst_w, dy + dst_h, 0, 0, src_w,
				src_h, null);
	}

	public synchronized void displayImageAndText(String filepath, String text,
			String color) {

		imageFile = filepath;
		textMessage = text;
		textColor = color;
		centerTextOnly = false;

		repaint();
		// System.out.println("Loading" + filepath);
	}

	public void paintText(Graphics2D g2d) {
		if (textMessage == null) {
			// System.out
			// .println("textMessage is null so not printing any text message");
			return;
		}

		if (centerTextOnly) {
			drawCenteredText(g2d);
			return;
		}
		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);
		Font font = new Font("Serif", Font.PLAIN, 80);
		g2d.setFont(font);

		defaultColor = g2d.getColor();
		if (textColor != null && !textColor.isEmpty()) {
			Color c = nameColorMap.get(textColor.toLowerCase());
			if (c != null)
				g2d.setColor(c);
			else
				System.out.println(textColor + "not a valid color");
		}
		paintText(g2d, textMessage);

		// g2d.drawString(textMessage,WIDTH / 2, yImage/2);
		g2d.setColor(defaultColor);
	}

	private void paintText(Graphics2D g2d, String st) {
		FontRenderContext fontRendContext = g2d.getFontRenderContext();
		Rectangle2D rect = g2d.getFont().getStringBounds(st, fontRendContext);
		float width = (float) rect.getWidth();
		float x = (WIDTH / 2) - (width / 2);
		if(yImage == -1) {yImage = HEIGHT/2;}
		float y = yImage / 2;
		// System.out
		// .println("drawing string " + st + " at (" + x + "," + y + ")");
		g2d.drawString(st, x, y);
	}

	public synchronized void sayIt(String sound) {
		readText.consume(sound);
	}

	public synchronized void playSound(String sound) {

		String wav = ".wav";
		int index = sound.indexOf(wav);
		if (index == -1) {
			readText.consume(sound);
			return;
		}

		File soundFile = new File(Element.getAbsolutePath(sound));

		AudioInputStream audioInputStream = null;
		try {
			audioInputStream = AudioSystem.getAudioInputStream(soundFile);
		} catch (Exception e) {
			System.out.println("" + e);
			return;
		}

		AudioFormat audioFormat = audioInputStream.getFormat();

		SourceDataLine line = null;
		DataLine.Info info = new DataLine.Info(SourceDataLine.class,
				audioFormat);
		try {
			line = (SourceDataLine) AudioSystem.getLine(info);
			line.open(audioFormat);
		} catch (LineUnavailableException e) {
			System.out.println("" + e);
		} catch (Exception e) {
			System.out.println("" + e);
		}

		line.start();

		int nBytesRead = 0;
		byte[] abData = new byte[EXTERNAL_BUFFER_SIZE];
		while (nBytesRead != -1) {
			try {
				nBytesRead = audioInputStream.read(abData, 0, abData.length);
			} catch (IOException e) {
				e.printStackTrace();
			}
			if (nBytesRead >= 0) {
				line.write(abData, 0, nBytesRead);
			}
		}

		line.drain();
		line.close();
	}

	private synchronized void drawCenteredText(Graphics2D g2d) {
		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);
		Font font = new Font("Serif", Font.PLAIN, 100);
		g2d.setFont(font);

		// center text
		FontMetrics fm = g2d.getFontMetrics();
		int x = (WIDTH - fm.stringWidth(textMessage)) / 2;
		int y = (fm.getAscent() + (HEIGHT - (fm.getAscent() + fm.getDescent())) / 2);
		defaultColor = g2d.getColor();
		if (textColor != null) {
			Color c = nameColorMap.get(textColor.toLowerCase());
			if (c != null)
				g2d.setColor(c);
			else
				System.out.println(textColor + "not a valid color");
		}
		g2d.drawString(textMessage, x, y);
		g2d.setColor(defaultColor);
	}

	public synchronized void drawCenteredString(String s, String color) {
		centerTextOnly = true;
		textMessage = s;
		textColor = color;
		imageFile = null;
		repaint();
	}
}